﻿#ifndef DATASTREAM_H
#define DATASTREAM_H

#include <string>
#include <vector>
#include <map>


#include <stream.h>
#include <metatypedef_p.h>
#include <ReflectX_global.h>

class REFLECTX_EXPORT ParseException :public StreamException {
public:
	ParseException(const char* msg);
};

class REFLECTX_EXPORT DataInputStream :public InputStream {
public:
	DataInputStream(InputStream* next);
	
	//读取POD类型
	template <typename T>
	typename std::enable_if<std::is_pod<T>::value, DataInputStream&>::type operator >> (T& t) throw (StreamException) {
		constexpr int typeSize = sizeof(T);
		unsigned char buffer[typeSize];

		int read_len = (*this).read(buffer, typeSize);

		if (typeSize > read_len) {
			throw ParseException("Parse Error");
		}

		t = *(T*)buffer;

		return *this;
	}

	//读取vector类型
	template <typename T>
	DataInputStream& operator >> (std::vector<T>& t) throw (StreamException) {
		t.clear();
		int size;
		(*this) >> size;

		if (size < 0) {
			throw ParseException("Parse Error");;
		}

		for (int i = 0; i < size; i++) {
			T r;
			(*this) >> r;
			t.push_back(r);
		}

		return (*this);
	}

	//读取map类型
	template <typename T, typename Key>
	DataInputStream& operator >> (std::map<Key, T>& t) throw (StreamException) {
		t.clear();
		int size;
		(*this) >> size;

		if (size < 0) {
			throw ParseException("Parse Error");
		}

		for (int i = 0; i < size; i++) {
			Key k;
			T val;
			(*this) >> k;
			(*this) >> val;
			t[k] = val;
		}

		return (*this);
	}

	//读取字符串或字节串类型
	DataInputStream&  operator >> (std::string& t) throw (StreamException);
	DataInputStream&  operator >> (std::wstring& t) throw (StreamException);
	DataInputStream&  operator >> (ByteArray& t) throw (StreamException);

protected:
	int doRead(unsigned char* buffer, int readLen) throw(StreamException)override;

};

class REFLECTX_EXPORT DataOutputStream :public OutputStream {
public:
	DataOutputStream(OutputStream* next);
	void write(const unsigned char* buffer, int len) throw (StreamException)override;

	//输出POD类型
	template<typename T>
	typename std::enable_if<std::is_pod<T>::value, DataOutputStream&>::type operator << (const T& t) {
		(*this).write((const unsigned char*)&t, sizeof(t));
		return *this;
	}

	//输出vector类型
	template <typename T>
	DataOutputStream& operator << (const std::vector<T>& t) {

		(*this) << (int)t.size();
		for (const T & i : t) {
			(*this) << i;
		}

		return *this;
	}

	//输出map类型
	template <typename T, typename Key>
	DataOutputStream& operator << (const std::map<Key, T>& t) {
		(*this) << (int)t.size();

		for (auto i : t) {
			(*this) << i.first;
			(*this) << i.second;
		}

		return (*this);
	}


	//输出字符串或字节串类型
	DataOutputStream&  operator << ( const std::string& t);
	DataOutputStream&  operator << ( const std::wstring& t);
	DataOutputStream&  operator << (const ByteArray& t);

};

#endif // DATASTREAM_H
